/*
 * funcionesUtiles.c
 *
 *  Created on: 26/10/2011
 *      Author: utn_so
 */
#include "../../Commons/src/includes/nipc.h"
#include "./includes/funcionesUtiles.h"
#include "./includes/colasPeticion.h"
#include "./includes/variablesGlobales.h"
#include "./includes/funcionesAlgoritmo.h"
#include <string.h>
#include<time.h>

char bufferLog[100];
time_t curtime;
struct tm *loctime;


#define BACKLOG 10

uint32_t esPDD(uint32_t socket,desc_PDD_t *vector_PDD,uint32_t limite){
	uint32_t i;

	for(i = 0; i < limite; ++i){
		if (vector_PDD[i].socket == socket){
			return 1;
		}
	}

	return 0;
}

uint32_t recibirCabecera(uint32_t socket,paqueteNIPC *cabecera){
	uint32_t bytes_recibidos;

	if((bytes_recibidos = recv(socket, cabecera, sizeof (*cabecera),0)) <= 0){
		return -1;
	}
	return bytes_recibidos;
}

void inicializarVectorPDDs(desc_PDD_t *vec, uint32_t n){
	uint32_t i;
	for(i=0; i<n; i++){
		vec[i].socket = -1;
		strcpy(vec[i].identificador,"\0");
		vec[i].hilo = -1;
		vec[i].flagSincro = -1;

//
		vec[i].colaFte = NULL;
		vec[i].colaFin = NULL;
	}
}

void quitarElementoDeVector(uint32_t elem,desc_PDD_t *vec,uint32_t n){

	uint32_t i,j,g,m,z,r, sockPDD;
	ptrNodo colaFrenteAux, colaFinAux;
	g=1;
	m=n-1;
	z=1;



	for(i = 0; i < n; i++){
		if(vec[i].socket == elem){
			colaFrenteAux = vec[i].colaFte;
			colaFinAux = vec[i].colaFin;
			sockPDD = vec[i].socket;
			for(j = i; j < n; j++){
			i=j+1;
				memcpy(&vec[j], &vec[i], sizeof(desc_PDD_t));
			};
			//return;
		}
	}

			while(g==1){ //Pedidos del RAID
				if(estaVacia(colaFrenteAux)){
						//			printf("La cola de este disco esta vacía");
					g=0;

					} else {
						switch(colaFrenteAux->flagRW){
						case 0:
							//(param->colaFte->flagRW == 0){ //Es Lectura
							otorgarPeticionDisco(colaFrenteAux->peticion, m, sectoresPorDisco, desc_PDD, colaFrenteAux->socket);
							suprimir(&colaFrenteAux, &colaFinAux);
							break;
						case 3:
							otorgarPeticionDiscoSincro(colaFrenteAux->peticion,m,sectoresPorDisco,desc_PDD);
							suprimir(&colaFrenteAux, &colaFinAux);
							break;
						default:
							break;
						}
					}
			}

//	while(z){
//	z=reencolarNodoAux(colaAuxFte,sockPDD,m);
//	}

}

uint32_t analizarTipo(uint32_t plength){

	if(plength == 0){ //Se conecto un pfs
		return 1;
	}else { //Se conecto un pdd
		return 0;
	}
	return -1; //ERROR
}

void armarCabecera(uint32_t num_msg,long longitud,paqueteNIPC* cabecera){
	cabecera->num_msg = num_msg;
	cabecera->longitud = longitud;
}


void tomarPeticion(desc_PDD_t *param){
	paqueteNIPC paquete;
//	time_t curtime;
	struct tm *loctime;
	nodo_t nodoAux;

	while(1){
		if(estaVacia(param->colaFte)){
			//			printf("La cola de este disco esta vacía");
		} else {
			switch(param->colaFte->flagRW){
			case 0:
				//(param->colaFte->flagRW == 0){ //Es Lectura
				if(pedirLecturaSockete(param->socket,param->colaFte->peticion, paquete, param->colaFte->socket)){;

				nodoAux.flagRW = 0;
				nodoAux.lonMsj = sizeof(uint32_t);
				strcpy(nodoAux.mensaje,"");
				nodoAux.peticion = param->colaFte->peticion;
				nodoAux.socket = param->socket;
			//	agregar(&colaAuxFte, &colaAuxFin, nodoAux);

				suprimir(&param->colaFte,&param->colaFin);
				} else {
				//	printf("No se pudo leer");
				}
				break;
			case 1:
				//if(param->colaFte->flagRW == 1){ //Es Escritura
				if(pedirEscrituraSockete(param->socket,param->colaFte->peticion,param->colaFte->mensaje,param->colaFte->lonMsj,param->colaFte->socket)){
					suprimir(&param->colaFte,&param->colaFin);
				} else {
			//		printf("No se pudo escribir");
				}
				break;
			case 2:
				if(pedirEscrituraSocketePanicso(param->socket,param->colaFte->peticion,param->colaFte->mensaje,param->colaFte->lonMsj)){
					if(param->colaFte->peticion==(sectoresPorDisco-1)){
						param->flagSincro = 1;
			//			printf("Su flag sincro dice %d",desc_PDD[1].flagSincro);
					//	puts("Terminó de sincronizar");
						if(flagConsola==1){

							curtime = time (NULL);
							loctime = localtime (&curtime);
							printf("Terminó de sincronizar el disco: \n %s\n",param->identificador);
							fputs (asctime (loctime), stdout);
						//	sectoresPorDisco=1048576;
						};

					};
					suprimir(&param->colaFte,&param->colaFin);
				} else {
				//	printf("No se pudo escribir para sin");
				}
				break;
			case 3:
				if(pedirLecturaSocketePanicso(param->socket,param->colaFte->peticion,paquete)){
					suprimir(&param->colaFte,&param->colaFin);
//					puts("leyo para sin");
				} else {
				//	printf("No se pudo leer sin");
				}
				break;
			default:
				break;
			};
		};
	};
}

uint32_t pedirLecturaSockete(uint32_t socket, uint32_t numSector, paqueteNIPC paquete, uint32_t socket_PFS){ //Devolver el paquete
	paqueteNIPC *paqueteP;
	payloadEscritura_t payloadEscritura;

	paqueteP = malloc(sizeof(paqueteNIPC));


	paqueteP->num_msg = 1;
	paqueteP->longitud = sizeof(uint32_t);
//	memcpy(&sectorCast,numSector,sizeof(sectorCast));
//	paquete.payload = malloc(sizeof(uint32_t));
//	memset(paqueteP->payload, '\0', 516);
	payloadEscritura.sector=numSector;
	payloadEscritura.socket=socket_PFS;
	memset(payloadEscritura.contenido,'\0',512);
	memcpy(&paqueteP->payload,&payloadEscritura,sizeof(payloadEscritura_t));


	if(send(socket,paqueteP,sizeof(paquete),0) == -1){
		perror("send");
		if(flagLog!=0){
						sprintf(bufferLog,"error al enviar peticion de lectura al PDD");
						agregarEntradaLog("Error",bufferLog);}
	//	puts("error al enviar peticion de lectura al PDD");
		return 0;
	} else {
//		puts("Se envió del RAID al PDD");
	};

	free(paqueteP);
//	puts("Leyó");
	return 1;
}

uint32_t pedirEscrituraSockete(uint32_t socket, uint32_t numSector, char mensaje[512], uint32_t longMsj, uint32_t socket_PFS){
	paqueteNIPC paquete;
	paqueteNIPC *paqueteP;
	payloadEscritura_t payloadEscritura;


	paqueteP = malloc(sizeof(paqueteNIPC));


	paqueteP->num_msg = 3;
	paqueteP->longitud = sizeof(uint32_t)+sizeof(payloadEscritura.contenido)+ sizeof(payloadEscritura.socket);
//	memcpy(&sectorCast,numSector,sizeof(sectorCast));
//	paquete.payload = malloc(sizeof(uint32_t));

	payloadEscritura.sector = numSector;
	memcpy(&payloadEscritura.contenido,mensaje,sizeof(payloadEscritura.contenido));
	payloadEscritura.socket=socket_PFS;

	memset(paqueteP->payload, '\0', 520);
	memcpy(&paqueteP->payload,&payloadEscritura,sizeof(payloadEscritura));


	if(send(socket,paqueteP,sizeof(paquete),0) == -1){
		perror("send");
		if(flagLog!=0){
					sprintf(bufferLog,"error al enviar peticion de lectura al PDD");
				agregarEntradaLog("Error",bufferLog);}
	//	puts("error al enviar peticion de lectura al PDD");
		return 0;
	} else {
//		puts("Se envió del RAID al PDD");
	};
		free(paqueteP);
//		puts("Escribió");
		return 1;
}

uint32_t pedirLecturaSocketePanicso(uint32_t socket, uint32_t numSector, paqueteNIPC paquete){
	paqueteNIPC *paqueteP;

	paqueteP = malloc(sizeof(paqueteNIPC));


	paqueteP->num_msg = 5;
	paqueteP->longitud = sizeof(uint32_t);
//	memcpy(&sectorCast,numSector,sizeof(sectorCast));
//	paquete.payload = malloc(sizeof(uint32_t));
	memset(paqueteP->payload, '\0', 516);
	memcpy(&paqueteP->payload,&numSector,sizeof(uint32_t));


	if(send(socket,paqueteP,sizeof(paquete),0) == -1){
		perror("send");
		if(flagLog!=0){
					sprintf(bufferLog,"error al enviar peticion de lectura al PDD");
					agregarEntradaLog("Error",bufferLog);}
//		puts("error al enviar peticion de lectura al PDD");
		return 0;
	} else {
//		puts("Se envió del RAID al PDD");
	};



	free(paqueteP);
//	puts("Leyó");
	return 1;
}

uint32_t pedirEscrituraSocketePanicso(uint32_t socket, uint32_t numSector, char mensaje[512], uint32_t longMsj){
	paqueteNIPC paquete;
	paqueteNIPC *paqueteP;
	payloadEscritura_t payloadEscritura;


	paqueteP = malloc(sizeof(paqueteNIPC));


	paqueteP->num_msg = 6;
	paqueteP->longitud = sizeof(uint32_t)+sizeof(payloadEscritura.contenido);
//	memcpy(&sectorCast,numSector,sizeof(sectorCast));
//	paquete.payload = malloc(sizeof(uint32_t));

	payloadEscritura.sector = numSector;
	memcpy(&payloadEscritura.contenido,mensaje,sizeof(payloadEscritura.contenido));

	memset(paqueteP->payload, '\0', 516);
	memcpy(&paqueteP->payload,&payloadEscritura,sizeof(payloadEscritura));


	if(send(socket,paqueteP,sizeof(paquete),0) == -1){
		perror("send");

		if(flagLog!=0){
						sprintf(bufferLog,"error al enviar peticion de lectura al PDD");
						agregarEntradaLog("Error",bufferLog);}
		//puts("error al enviar peticion de lectura al PDD");
		return 0;
	} else {
//		puts("Se envió del RAID al PDD");
		contador++;
	};



		free(paqueteP);
//		puts("Escribió");
		return 1;
}

void sincronizar(sincro_t *param){
uint32_t m, n, j;

j = 0;
	for(n=0; n<param->sectoresPorDisco; n++){
		m = 0;
		if(j==1000){
			j=0;
			while(contador<1000){
			sleep(1);
			};
			contador = 0;
		}

		j++;

//		if(m==3){
//			usleep(3000);
//			m=0;
//		}
//		m++;

//usleep(2000);
//		while(param->desc_PDD[m].flagSincro == 0) {
//			m++;
//		}
//		pedirLecturaSocketePanicso(param->desc_PDD[m].socket,n,paquete); //n
		otorgarPeticionDiscoSincro(n,((param->cantPDD)+1),param->sectoresPorDisco,desc_PDD);
//		 if (n%2 == 0){
//		usleep(1500);
//		 };
	//	usleep(300);
//		if(n==(param->sectoresPorDisco)-1){
//			desc_PDD[param->cantPDD].flagSincro = 1;
//			puts("Terminó de sincronizaar");
//		}
//
//		while(estaVacia(param->colaFte)){
//
//		};
//		pedirEscrituraSocketePanicso(param->desc_PDD[param->cantPDD].socket,param->colaFte->peticion,param->colaFte->mensaje,param->colaFte->lonMsj);
				//	printf("Se escribió el sector %d", param->colaFte->peticion);
				//puts("Pasó");
//					suprimirColaSincro(&param->colaFte,&param->colaFin);
//
//		usleep(31);
		while(semaforo<0){
		sleep(1);
		};
	};
};

